package br.pesquisa.lsystem;

import java.util.LinkedList;
import java.util.List;
import java.util.Observable;

import br.pesquisa.lsystem.Celula.Sentido;

public class Interpretador<T> extends Observable implements Runnable {
	private Gramatica<T> gramatica;
	private List<T> estado;
	private Integer numeroIteracoes;

	private volatile boolean animar;
	private volatile Integer delay;

	public Interpretador() {
		numeroIteracoes = 10;
		animar = false;
		delay = 0;
	}

	public Gramatica<T> getGramatica() {
		return gramatica;
	}

	public void setGramatica(Gramatica<T> gramatica) {
		this.gramatica = gramatica;
	}

	public List<T> getEstado() {
		return estado;
	}

	public void setEstado(List<T> estado) {
		this.estado = estado;
	}

	public Integer getNumeroIteracoes() {
		return numeroIteracoes;
	}

	public void setNumeroIteracoes(Integer numeroIteracoes) {
		this.numeroIteracoes = numeroIteracoes;
	}

	public boolean isAnimar() {
		return animar;
	}

	public void setAnimar(boolean animar) {
		this.animar = animar;
	}

	public Integer getDelay() {
		return delay;
	}

	public void setDelay(Integer delay) {
		this.delay = delay;
	}

	public void executar() {
		for (int i = 0; i < numeroIteracoes && !Thread.interrupted(); i++) {
			executarPasso();
			if (animar) {
				try {
					Thread.sleep(delay);
				} catch (InterruptedException e) {
					break;
				}
			}
		}
	}

	public void executarPasso() {
		estado = gramatica.aplicarProducoes(estado);
		setChanged();
		notifyObservers();
		System.out.println(estado);
	}

	public void run() {
		this.executar();
	}

	public static void main(String[] args) throws Exception {
		Interpretador<Celula> interpretador = new Interpretador<Celula>();

		Alfabeto<Celula> alfabeto = new Alfabeto<Celula>();
		Celula smallCell = new Celula("S", Sentido.direita);
		alfabeto.adicionar(smallCell);
		Celula largeCell = new Celula("L", Sentido.direita);
		alfabeto.adicionar(largeCell);

		interpretador.setGramatica(new Gramatica<Celula>());
		interpretador.getGramatica().setAlfabeto(alfabeto);
		interpretador.getGramatica().getAxioma().add(largeCell);

		Producao<Celula> producao = new Producao<Celula>();
		producao.setPredecessor(largeCell);
		producao.getSucessor().add(largeCell);
		producao.getSucessor().add(smallCell);
		interpretador.getGramatica().adicionarProducao(producao);

		producao = new Producao<Celula>();
		producao.setPredecessor(smallCell);
		producao.getSucessor().add(largeCell);
		interpretador.getGramatica().adicionarProducao(producao);

		interpretador.setEstado(new LinkedList<Celula>());
		interpretador.getEstado().addAll(
				interpretador.getGramatica().getAxioma());

		System.out.println("Producoes: ");
		System.out.println(interpretador.getGramatica().getProducoes());
		System.out.println("Transicoes: ");
		System.out.println(interpretador.getEstado());
		Thread thread = new Thread(interpretador);
		thread.start();
		thread.join();
	}
}
